package it.basilikos.core.model.dao.impl;

 
	import it.basilikos.core.model.dao.IBaseDAO;
import it.basilikos.core.util.Condition;

import java.io.Serializable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.google.common.base.Preconditions;

	/***
	 * 
	 * @author Domenico Grieco
	 *
	 * @param <T> Entity
	 * @param <I> Id Class
	 */
//	@Repository
	@Transactional
	public class BaseDAO<T extends Serializable, I extends Comparable<I>> implements IBaseDAO<T,I>{

		private static final Logger log = LoggerFactory.getLogger(BaseDAO.class);

		protected final Class<T> clazz;

		@Autowired
		@PersistenceContext
		protected EntityManager entityManager;

		
		
		public BaseDAO(final Class<T> clazzToSet) {
			this.clazz = clazzToSet;
		}

		@Override
		public T findById(final I id) {
			Preconditions.checkArgument(id != null);
			T e = getEntityManager().find(clazz, id);
			return e;
		}
		

		@Override
		public List<T> findByProperties(final Condition condition) {
//			TODO implement this methods
			log.error("(findByProperties) THIS METHOD IS NOT IMPLEMENTED");
			return null;
//			Criteria criteria = getEntityManager().create
//					
//					.createCriteria(
//	                AppRole.class);
//	        criteria.add(Restrictions.ilike("roleName", roleName + "%"));
//	        return criteria.list();
//			getEntityManager().find(arg0, arg1, arg2)
//			return null;
		}


		
		@Override
		@SuppressWarnings("unchecked")
		public List<T> findAll() {
			return getEntityManager().createQuery("from " + clazz.getName()).getResultList();
		}

		@Override
		public T create(final T entity) {
			log.info("Making " + entity + " persistent ..");
			Preconditions.checkNotNull(entity);
			getEntityManager().persist(entity);
			return entity;
		}

		@Override
		public T update(final T entity) {
			Preconditions.checkNotNull(entity);
			return (T) getEntityManager().merge(entity);
		}

		@Override
		public void delete(final T entity) {
			Preconditions.checkNotNull(entity);
			getEntityManager().remove(entity);
		}

		@Override
		public void deleteById(final I entityId) {
			log.info("Deleting by Id: " + entityId);
			final T entity = findById(entityId);
			Preconditions.checkState(entity != null);
			delete(entity);
		}		
		
		public EntityManager getEntityManager() {
			return entityManager;
		}

		public void setEntityManager(EntityManager entityManager) {
			this.entityManager = entityManager;
		}
	
}
